﻿using System;
using System.Linq;
using System.Reflection;
using XEvolve.Core.Runtime.Attributes;

namespace XEvolve.Core.Runtime.Internal
{
    internal class PicoBasedPlatform : Platform
    {
        private const string PLUGINS = "xevolve.plugins";
        private readonly PicoBasedExtensionRegistry registry;

        public PicoBasedPlatform()
        {
            registry = new PicoBasedExtensionRegistry();            
            registry.RegisterExtensionPoint(PLUGINS);
            InstallCorePlugin();
        }

        private void InstallCorePlugin()
        {
            var corePlugin = new CorePlugin();
            registry.RegisterExtension(PLUGINS, GetPluginIdentifier(typeof(CorePlugin)), corePlugin);
            corePlugin.Install(this);
        }

        public override void RegisterService(Type api, Type implementation)
        {
            registry.RegisterService(api, implementation);
        }

        public override void RegisterService(Type api, object instance)
        {
            registry.RegisterService(api, instance);
        }

        public override void RegisterService<Api, Implementation>()
        {
            RegisterService(typeof(Api), typeof(Implementation));
        }

        public override void Start()
        {
            registry.Start();
        }

        public override void Stop()
        {
            registry.Stop();
        }

        public override IExtensionRegistry Registry
        {
            get { return registry; }
        }

        public override IServiceLocator ServiceLocator
        {
            get { return registry; }
        }

        public override void InstallPlugins(IPluginProvider pluginProvider)
        {
            foreach (var pluginType in pluginProvider.Plugins.Where(plugin => plugin != typeof(CorePlugin)))
            {
                registry.RegisterExtension(PLUGINS, GetPluginIdentifier(pluginType), pluginType);
            }
            foreach (Plugin plugin in registry.GetExtensionPoint(PLUGINS).Extensions)
            {
                plugin.Install(this);
            }
        }

        private static object GetPluginIdentifier(ICustomAttributeProvider pluginType)
        {
            return ((PluginIdAttribute)pluginType.GetCustomAttributes(typeof(PluginIdAttribute), false)[0]).Identifier;
        }
    }
}